﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using UtilZ.Dotnet.Ex.Base;
using UtilZ.Dotnet.Ex.Communication.Base;
using UtilZ.Dotnet.Ex.Communication.Net.Telnet;
using UtilZ.Dotnet.Ex.Log;

namespace ConAppCore
{
    internal class TestTelnetServer : IDisposable
    {
        private readonly TelnetServer _telnetServer;
        private TestTelnetServer()
        {
            int port = 2300;
            var config = new TelnetConfig()
            {
                Port = port,
                Users = new TelnetUserInfo[]
                {
                    new TelnetUserInfo("yf","yf")
                }
            };
            this._telnetServer = new TelnetServer(this.ProcessTelnetMessage, config);
            this._telnetServer.ConnectedPromptMessage = "<<<XX服务>>>";
            this._telnetServer.Start();
            Loger.Info($"TelnetServer started.端口{port}..");
        }

        private string ProcessTelnetMessage(TelnetMessageArgs args)
        {
            try
            {
                var message = args.Message;
                if (string.IsNullOrWhiteSpace(message))
                {
                    return string.Empty;
                }

                message = message.ToLower().Trim();
                //string[] paraArr = message.Split(this._splitChArr, StringSplitOptions.RemoveEmptyEntries);

                if (message.StartsWith("-"))
                {
                    message = message.Trim(new char[] { '-' });
                }

                string result;
                switch (message)
                {
                    case "help":
                        StringBuilder sb = new StringBuilder();
                        sb.AppendLine(string.Format("{0, -10}帮助", "help"));
                        sb.AppendLine(string.Format("{0, -10}全部告警列表", "info"));
                        sb.AppendLine(string.Format("{0, -10}离线告警列表", "awl"));
                        sb.AppendLine(string.Format("{0, -10}UI数据", "ui"));
                        result = sb.ToString();
                        break;
                    case "l":
                        this.OutputLog(args);
                        result = "log output";
                        break;
                    case "q":
                        this._logFlag = false;
                        result = "stop log";
                        break;
                    case "owl":
                        result = "this.DebugQuery()";
                        break;
                    default:
                        result = "this.DebugQuery(message)";
                        break;
                }

                return result;
            }
            catch (Exception ex)
            {
                Loger.Error(ex);
                return ex.ToString();
            }
        }


        /// <summary>
        /// 收到消息的telnet客户端
        /// </summary>
        private IListenTelnetClient _telnetClient = null;
        private void OutputLog(TelnetMessageArgs args)
        {
            if (this._telnetClient == null)
            {
                this._telnetClient = args.TelnetClient;
                this._telnetClient.ConnectChanged += _telnetClient_ConnectChanged;
                var redirectAppenderToUI = (RedirectAppender)Loger.GetAppenderByName(null, "RedirectToUI");
                if (redirectAppenderToUI != null)
                {
                    redirectAppenderToUI.RedirectOuput += RedirectLogOutput;
                }
            }

            this._logFlag = true;
            Task.Factory.StartNew(TestLog);
        }

        private void _telnetClient_ConnectChanged(object sender, UtilZ.Dotnet.Ex.Communication.Net.Base.NetConnectedChangedArgs e)
        {
            this._telnetClient = null;
        }

        private bool _logFlag = false;
        private void TestLog()
        {
            Thread.Sleep(1000);
            Random rnd = new Random();
            var list = EnumEx.GetEnumFieldInfoList(typeof(LogLevel));
            int rndValue;
            LogLevel level;
            string logMsg;

            while (this._logFlag)
            {
                rndValue = rnd.Next(0, list.Count);
                level = (LogLevel)list[rndValue].Value;
                logMsg = $"{TimeEx.GetTimestamp()}时间XXXX";
                switch (level)
                {
                    case LogLevel.Trace:
                        Loger.Trace(logMsg);
                        break;
                    case LogLevel.Debug:
                        Loger.Debug(logMsg);
                        break;
                    case LogLevel.Info:
                        Loger.Info(logMsg);
                        break;
                    case LogLevel.Warn:
                        Loger.Warn(logMsg);
                        break;
                    case LogLevel.Error:
                        Loger.Error(logMsg);
                        break;
                    case LogLevel.Fatal:
                        Loger.Fatal(logMsg);
                        break;
                    case LogLevel.Off:
                        continue;
                }

                Thread.Sleep(rndValue * 1000 / 6);
            }
        }

        private void RedirectLogOutput(object sender, RedirectOuputArgs e)
        {
            var telnetClient = this._telnetClient;
            if (telnetClient != null && telnetClient.Status == ConnectionStatus.Opened)
            {
                try
                {
                    string str;
                    try
                    {
                        var item = e.Item;
                        str = string.Format("{0} {1}", e.Item.Time.ToString(LogConstant.DateTimeFormat), e.Item.Message);
                    }
                    catch (Exception ex)
                    {
                        str = $"{ex.Message}";
                    }
                    str = $"{TelnetConstant.END_LINE_CURSOR}{str}";

                    telnetClient.SendMessage(str);
                }
                catch (Exception ex)
                {
                    this._telnetClient = null;
                    Console.WriteLine(ex.Message);
                }
            }
        }



        public void Dispose()
        {
            this._telnetServer.Stop();
            this._telnetServer.Dispose();
        }


        private static TestTelnetServer _instance = null;
        public static void Test()
        {
            if (_instance != null)
            {
                return;
            }

            _instance = new TestTelnetServer();
        }

        public static void Release()
        {
            if (_instance != null)
            {
                _instance.Dispose();
            }
        }

    }
}
